﻿#include "Grammar.h"
#include"lexer.h"
using namespace std;

 SymbolTable symbolTable;
 vector<Quadruple> quads;
 int nxq; // Next quadruple index
 int OFFSET; // Global offset counter for variable declarations
 // --- Semantic Action Helper Functions ---
 inline PatchList mklist(int i) {
	 return{ i };
 }
 inline PatchList mklist() {
	 return{  };
 }

 inline PatchList merge(const PatchList& p1, const PatchList& p2) {
	 PatchList result = p1;
	 result.insert(result.end(), p2.begin(), p2.end());
	 return result;
 }


 // Helper to map Lexer token types to Grammar terminal names
 inline string mapTokenToTerminal(const Token& token) {
	 if (token.type == "INTSYM") return "int";
	 if (token.type == "DOUBLESYM") return "double";
	 if (token.type == "SCANFSYM") return "scanf";
	 if (token.type == "PRINTFSYM") return "printf";
	 if (token.type == "IFSYM") return "if";
	 if (token.type == "THENSYM") return "then";
	 if (token.type == "WHILESYM") return "while";
	 if (token.type == "DOSYM") return "do";
	 if (token.type == "COMMA") return ",";
	 if (token.type == "SEMICOLON") return ";";
	 if (token.type == "PLUS") return "+";
	 if (token.type == "MINUS") return "-";
	 if (token.type == "TIMES") return "*";
	 if (token.type == "DIVISION") return "/";
	 if (token.type == "AO" && token.value == "=") return "="; // Assignment
	 if (token.type == "RO") return token.value; // Relational Ops (==, !=, <, <=, >, >=)
	 if (token.type == "LO" && token.value == "!") return "!";
	 if (token.type == "LO" && token.value == "&&") return "&&";
	 if (token.type == "LO" && token.value == "||") return "||";
	 if (token.type == "BRACE" && token.value == "(") return "(";
	 if (token.type == "BRACE" && token.value == ")") return ")";
	 if (token.type == "BRACE" && token.value == "{") return "{";
	 if (token.type == "BRACE" && token.value == "}") return "}";
	 if (token.type == "IDENT") return "id";
	 if (token.type == "INT") return "UINT";
	 if (token.type == "DOUBLE") return "UFLOAT";

	 // Add other mappings as needed based on lexer.h and grammar
	 return ""; // Unknown or unmapped token
 }


 void backpatch(const PatchList& p, int quad_target) {
	 if (quad_target == -1) {
		 cerr << "Error: Attempting to backpatch with invalid target quad." << endl;
		 // Potentially set error flag
		 return;
	 }
	 string target_str = to_string(quad_target);
	 for (int quad_index : p) {
		 if (quad_index >= 0 && quad_index < quads.size()) {
			 // Patch the result field (destination address)
			 if (quads[quad_index].op[0] == 'j') { // Only patch jump instructions
				 quads[quad_index].result = target_str;
			 }
			 else {
				 // This might indicate an issue if trying to patch non-jump instructions
				 cerr << "Warning: Attempting to backpatch non-jump instruction at index " << quad_index << endl;
			 }
		 }
		 else {
			 cerr << "Error: Invalid quadruple index " << quad_index << " in backpatch list." << endl;
			 // Potentially set error flag
		 }
	 }
 }


 // gen function - needs careful handling of types and formatting
  void gen(const string& op, const string& arg1, const string& arg2, const string& result) {
	 // Special formatting for float literals in '=' assignment
	 string formatted_arg1 = arg1;
	 if (op == "=" && !arg1.empty() && arg1 != "-") {
		 try {
			 size_t processed = 0;
			 double val = stod(arg1, &processed);
			 // Check if the entire string was consumed and it contains a decimal or 'e'/'E'
			 bool isFloatLiteral = (processed == arg1.length() && (arg1.find('.') != string::npos || arg1.find('e') != string::npos || arg1.find('E') != string::npos));
			 if (isFloatLiteral){
				 stringstream ss;
				 ss << fixed << setprecision(6) << val;
				 formatted_arg1 = ss.str();
			 }
		 }
		 catch (const std::invalid_argument& ia) {
			 // Not a number, keep original
		 }
		 catch (const std::out_of_range& oor) {
			 // Out of range, keep original (or handle error)
		 }
	 }

	 quads.emplace_back(op, formatted_arg1, arg2, result);
	 nxq++; // Increment next quadruple index
 }
// 辅助函数：分割字符串
vector<string> split(const string& s, char delimiter) {
    vector<string> tokens;
    string token;
    istringstream tokenStream(s);
    while (getline(tokenStream, token, delimiter)) {
        tokens.push_back(token);
    }
    // 处理末尾的空字符串（如果需要）
    if (!s.empty() && s.back() == delimiter) {
        // 如果字符串以分隔符结尾，可能会多一个空token，根据需要处理
        // 这里暂时不处理，因为我们的格式不会这样
    }
    return tokens;
}

// 辅助函数：去除字符串首尾空格
string trim(const string& str) {
    size_t first = str.find_first_not_of(" \t\n\r");
    if (string::npos == first) {
        return str;
    }
    size_t last = str.find_last_not_of(" \t\n\r");
    return str.substr(first, (last - first + 1));
}


Grammar::Grammar(string inputfile) {
    ifstream infile(inputfile);
    if (!infile.is_open()) {
        cerr << "Error: Cannot open input file: " << inputfile << endl;
        // 可以选择抛出异常或采取其他错误处理方式
        return;
    }

    string line;
    enum class ParseState { NONE, TERMINAL, NON_TERMINAL, PRODUCTION };
    ParseState currentState = ParseState::NONE;

    // 添加默认的EOF符号$
    terminals.insert({ "$", TERMINAL });

    while (getline(infile, line)) {
        line = trim(line); // 去除首尾空格
        if (line.empty() || line[0] == '[') { // 跳过空行和注释行
            // 简单跳过以 '[' 开头的行（假设它们是源注释）
            continue;
        }


        if (line == "TERMINAL:") {
            currentState = ParseState::TERMINAL;
            continue;
        }
        else if (line == "NON_TERMINAL:") {
            currentState = ParseState::NON_TERMINAL;
            continue;
        }
        else if (line == "PRODUCTION:") {
            currentState = ParseState::PRODUCTION;
            // 添加增广产生式 (假设第一个非终结符是开始符号)
            getline(infile, line);
            Production augProd;
            // 创建一个新的非终结符作为增广文法的开始符号
            string augStartName = line + "'";
            nonTerminals.insert({ augStartName, NON_TERMINAL }); // 需要先添加，否则后面setStartSymbol会找不到
            augProd.left = { augStartName, NON_TERMINAL };
            augProd.right = { {line,NON_TERMINAL } }; // 使用第一个读取到的非终结符
            this->addProduction(augProd);
            this->setStartSymbol(augProd.left); // 设置增广文法的开始符号
            
         
            continue;
        }


        switch (currentState) {
        case ParseState::TERMINAL: {
            stringstream ss(line);
            string terminalName;
            while (ss >> terminalName) {
                terminals.insert({ terminalName, TERMINAL });
            }
            break;
        }
        case ParseState::NON_TERMINAL: {
            stringstream ss(line);
            string nonTerminalName;
            bool isFirstNonTerminal = nonTerminals.empty(); // 检查是否是第一个非终结符
            while (ss >> nonTerminalName) {
                nonTerminals.insert({ nonTerminalName, NON_TERMINAL });
                // 可以在这里记录第一个非终结符，用于后续设置开始符号
                // if (isFirstNonTerminal) { /* 记录 */ }
            }
            break;
        }
        case ParseState::PRODUCTION: {
            // 解析产生式: A -> B C D RULE::{...}
            size_t arrowPos = line.find("->");
            size_t rulePos = line.find("RULE::{");

            if (arrowPos == string::npos) {
                cerr << "Warning: Skipping invalid production line (missing '->'): " << line << endl;
                continue;
            }

            string leftStr = trim(line.substr(0, arrowPos));
            string rightStr;
            string semanticActionStr;

            if (rulePos != string::npos) {
                rightStr = trim(line.substr(arrowPos + 2, rulePos - (arrowPos + 2)));
                // 提取 RULE::{} 内的内容
                size_t ruleEndPos = line.find("}", rulePos);
                if (ruleEndPos != string::npos) {
                    semanticActionStr = trim(line.substr(rulePos + strlen("RULE::{"), ruleEndPos - (rulePos + strlen("RULE::{"))));
                }
                else {
                    cerr << "Warning: Malformed RULE section in line: " << line << endl;
                }
            }
            else {
                // 没有 RULE::{} 部分
                rightStr = trim(line.substr(arrowPos + 2));
            }


            Production prod;

            // 查找左部符号
            auto it_nt_left = find_if(nonTerminals.begin(), nonTerminals.end(),
                [&](const Symbol& s) { return s.name == leftStr; });
            if (it_nt_left != nonTerminals.end()) {
                prod.left = *it_nt_left;
            }
            else {
                cerr << "Error: Unknown non-terminal on left side: " << leftStr << " in line: " << line << endl;
                continue; // 跳过此产生式
            }


            // 解析右部符号
            stringstream ssRight(rightStr);
            string symbolStr;
            while (ssRight >> symbolStr) {
                if (symbolStr == "^") { // 处理空产生式
                    // 右部为空，不需要添加符号
                }
                else {
                    if (symbolStr.back()>='0'&&symbolStr.back()<='9')
                    {
                        while (symbolStr.back() != '_')
                            symbolStr.pop_back();
                        symbolStr.pop_back();
                    }
                    // 尝试在非终结符中查找
                    auto it_nt = find_if(nonTerminals.begin(), nonTerminals.end(),
                        [&](const Symbol& s) { return s.name == symbolStr; });
                    if (it_nt != nonTerminals.end()) {
                        prod.right.push_back(*it_nt);
                    }
                    else {
                        // 尝试在终结符中查找
                        auto it_t = find_if(terminals.begin(), terminals.end(),
                            [&](const Symbol& s) { return s.name == symbolStr; });
                        if (it_t != terminals.end()) {
                            prod.right.push_back(*it_t);
                        }
                        else {
                            cerr << "Error: Unknown symbol on right side: " << symbolStr << " in line: " << line << endl;
                            // 可以选择跳过或标记错误
                        }
                    }
                }
            }

            // 存储语义动作 (如果存在)
            if (!semanticActionStr.empty()) {
                // 目前只简单存储整个字符串，如果需要解析可以进一步处理
                prod.semanticAction.push_back(semanticActionStr);
            }

            this->addProduction(prod);
            break;
        }
        case ParseState::NONE:
            // 忽略PRODUCTION之前的内容（除了标记）
            break;
        }
    }

    infile.close();

    // 可以在这里添加对读取结果的验证，例如检查开始符号是否已设置等。
    if (startSymbol.name.empty() && !nonTerminals.empty()) {
        cerr << "Warning: Start symbol was not set automatically (likely no PRODUCTION section or empty non-terminals list before it)." << endl;
        // 可以根据需要设置一个默认的开始符号，或者要求用户指定
        // 例如，设置第一个读取到的非终结符为开始符号（如果增广文法未添加）
        // if (!productions.empty() && productions[0].left.name.find("'") == string::npos) { // 检查是否已添加增广文法
        //     setStartSymbol(*nonTerminals.begin());
        // }
    }
    else if (startSymbol.name.empty()) {
        cerr << "Error: No start symbol could be determined." << endl;
    }

}

inline void Grammar::addProduction(const Production& p) {
    productions.push_back(p);
}

inline void Grammar::setStartSymbol(const Symbol& s) {
    if (nonTerminals.count(s)) {
        startSymbol = s;
    }
    else {
        cerr << "Error: Attempted to set a non-non-terminal symbol as start symbol: " << s.name << endl;
    }
}

void Grammar::computeFirstSets() {
    // 初始化
    for (const auto& nt : nonTerminals) {
        first[nt];
    }
    for (const auto& t : terminals) {
        first[t] = { t };
    }

    bool changed;
    do {
        changed = false;
        for (const auto& p : productions) {
            const auto& A = p.left;
            const auto& beta = p.right;

            // 处理A -> β
            size_t oldSize = first[A].size();

            // 如果β为空，加入epsilon
            if (beta.empty()) {
                first[A].insert({ "epsilon", TERMINAL });
            }
            else {
                bool allHaveEpsilon = true;
                for (const auto& X : beta) {
                    // 将First(X) - {epsilon}加入First(A)
                    for (const auto& f : first[X]) {
                        if (f.name != "epsilon") {
                            first[A].insert(f);
                        }
                    }

                    // 如果X不能推导出epsilon，停止
                    if (first[X].find({ "epsilon", TERMINAL }) == first[X].end()) {
                        allHaveEpsilon = false;
                        break;
                    }
                }

                // 如果所有X都能推导出epsilon，加入epsilon
                if (allHaveEpsilon) {
                    first[A].insert({ "epsilon", TERMINAL });
                }
            }

            if (first[A].size() > oldSize) {
                changed = true;
            }
        }
    } while (changed);
}


 set<Symbol> Grammar::computeFirst(const vector<Symbol>& symbols) {
    set<Symbol> result;

    bool allHaveEpsilon = true;
    for (const auto& s : symbols) {
        for (const auto& f : first[s]) {
            if (f.name != "epsilon") {
                result.insert(f);
            }
        }

        if (first[s].find({ "epsilon", TERMINAL }) == first[s].end()) {
            allHaveEpsilon = false;
            break;
        }
    }

    if (allHaveEpsilon) {
        result.insert({ "epsilon", TERMINAL });
    }

    return result;
}

void Grammar::printFirstSets()  {
    cout << "First Sets:\n";
    // 最好按非终结符名称排序输出，以便观察
    vector<Symbol> sortedNonTerminals(nonTerminals.begin(), nonTerminals.end());
    sort(sortedNonTerminals.begin(), sortedNonTerminals.end());

    for (const auto& nt : sortedNonTerminals) {
        cout << "FIRST(" << nt.name << ") = { ";
        bool isFirst = true;
        auto it = first.find(nt);
        if (it != first.end()) {
            // 对First集内的符号也排序，以便输出一致
            vector<Symbol> sortedFirstSet(it->second.begin(), it->second.end());
            sort(sortedFirstSet.begin(), sortedFirstSet.end());

            for (const auto& s : sortedFirstSet) {
                if (!isFirst) cout << ", ";
                cout << s.name;
                isFirst = false;
            }
        }
        else {
            cout << "(Not computed)"; // 或者留空
        }
        cout << " }\n";
    }
}


  vector<LR1ItemSet> Grammar::buildLR1ItemSets() {
     // 初始项集
     LR1Item initialItem;
     initialItem.production = productions[0]; // 假设第一个产生式是增广产生式
     initialItem.dotPos = 0;
     initialItem.lookahead = { "$", TERMINAL };
     LR1ItemSet initialSet;
     initialSet.items.insert(initialItem);
     closure(initialSet);
     vector<LR1ItemSet> itemSets;
     initialSet.id = 0;
     itemSets.push_back(initialSet);
     queue<int> worklist;
     worklist.push(0);
     while (!worklist.empty()) {
         int currentId = worklist.front();
         worklist.pop();
         LR1ItemSet& currentSet = itemSets[currentId];
         // 对每个可能的符号X
         set<Symbol> symbols;
         for (const auto& item : currentSet.items) {
             Symbol next = item.nextSymbol();
             if (next.name != "") {
                 symbols.insert(next);
             }
         }
         for (const auto& X : symbols) {
             LR1ItemSet newSet;
             LR1ItemSet& currentSet = itemSets[currentId];
             gotoFunction(currentSet, X, newSet);
             if (newSet.items.empty()) continue;
             // 检查是否已经存在这个项集
             bool found = false;
             int existingId = -1;
             for (const auto& is : itemSets) {
                 if (is == newSet) {
                     found = true;
                     existingId = is.id;
                     break;
                 }
             }
             if (!found) {
                 newSet.id = itemSets.size();
                 itemSets.push_back(newSet);
                 worklist.push(newSet.id);
                 existingId = newSet.id;
             }
             // 记录转移
             if (X.type == TERMINAL) {
                 transitions[{currentId, X}] = existingId;
             }
             else {
                 nonTerminalTransitions[{currentId, X}] = existingId;
             }
         }
     }
     return itemSets;
 }


  LR1ParsingTable Grammar::buildLR1ParsingTable(const vector<LR1ItemSet>& itemSets) {
     LR1ParsingTable table;
     table.actionTable.resize(itemSets.size());
     table.gotoTable.resize(itemSets.size());
     // 填充action表
     for (const auto& entry : transitions) {
         int fromState = entry.first.first;
         Symbol sym = entry.first.second;
         int toState = entry.second;

         Action action;
         action.type = SHIFT;
         action.target = toState;

         table.actionTable[fromState][sym] = action;
     }

     // 填充reduce和accept动作
     for (size_t i = 0; i < itemSets.size(); i++) {
         const auto& itemSet = itemSets[i];
         for (const auto& item : itemSet.items) {
             if (item.isDotAtEnd()) {
                 // 如果是增广产生式的完成项
                 if (item.production.left.name == "PROG'" &&
                     item.production.right.size() == 1 &&
                     item.production.right[0].name == "PROG") {
                     Action action;
                     action.type = ACCEPT;
                     table.actionTable[i][{"$", TERMINAL}] = action;
                 }
                 else {
                     // 普通reduce动作
                     Action action;
                     action.type = REDUCE;

                     // 找到产生式编号
                     for (size_t p = 0; p < productions.size(); p++) {
                         if (productions[p].left.name == item.production.left.name &&
                             productions[p].right == item.production.right) {
                             action.target = p;
                             break;
                         }
                     }

                     table.actionTable[i][item.lookahead] = action;
                 }
             }
         }
     }

     // 填充goto表
     for (const auto& entry : nonTerminalTransitions) {
         int fromState = entry.first.first;
         Symbol sym = entry.first.second;
         int toState = entry.second;

         table.gotoTable[fromState][sym] = toState;
     }

     return table;
 }


  void Grammar::closure(LR1ItemSet& itemSet) {
     bool changed;
     do {
         changed = false;
         set<LR1Item> newItems;

         for (const auto& item : itemSet.items) {
             Symbol B = item.nextSymbol();
             if (B.type == NON_TERMINAL && B.name != "") {
                 vector<Symbol> beta;
                 for (size_t i = item.dotPos + 1; i < item.production.right.size(); i++) {
                     beta.push_back(item.production.right[i]);
                 }
                 beta.push_back(item.lookahead);

                 set<Symbol> firstBeta = computeFirst(beta);

                 // 对于B的每个产生式B -> γ
                 for (const auto& p : productions) {
                     if (p.left.name == B.name) {
                         for (const auto& b : firstBeta) {
                             LR1Item newItem;
                             newItem.production = p;
                             newItem.dotPos = 0;
                             newItem.lookahead = b;

                             if (itemSet.items.find(newItem) == itemSet.items.end() &&
                                 newItems.find(newItem) == newItems.end()) {
                                 newItems.insert(newItem);
                                 changed = true;
                             }
                         }
                     }
                 }
             }
         }

         for (const auto& item : newItems) {
             itemSet.items.insert(item);
         }
     } while (changed);
 }

   void Grammar::gotoFunction(const LR1ItemSet& I, Symbol X, LR1ItemSet& newSet) {
      for (const auto& item : I.items) {
          if (item.nextSymbol().name == X.name) {
              LR1Item newItem;
              newItem.production = item.production;
              newItem.dotPos = item.dotPos + 1;
              newItem.lookahead = item.lookahead;
              newSet.items.insert(newItem);
          }
      }

      if (!newSet.items.empty()) {
          closure(newSet);
      }
  }


   // --- Type Checking Helper ---
   bool Grammar::checkTypes(const string& place1, const string& place2, const string& operation,string result="") {
	   return true;
	   // Allow integer literals ('0') with variables for unary minus/plus
	   if ((operation == "unary+" || operation == "unary-") && place1 == "0") {
		   return true; // Assume place2 type is valid
	   }
	   if (place1 == "-") return true; // Placeholder for no arg
	   if (place2 == "-") return true; // Placeholder for no arg


	   VarType type1 = symbolTable.getTypeFromPlace(place1);
	   VarType type2 = symbolTable.getTypeFromPlace(place2);


	   // Handle literals (assuming they are correctly passed as strings)
	   // A more robust system would parse literals into Attributes
	   try {
		   size_t processed = 0;
		   stod(place1, &processed);
		   if (processed == place1.length()){ // Full string is a number
			   type1 = (place1.find('.') != string::npos || place1.find('e') != string::npos || place1.find('E') != string::npos) ? TYPE_DOUBLE : TYPE_INT;
		   }
	   }
	   catch (...){} // Ignore if not a number

	   try {
		   size_t processed = 0;
		   stod(place2, &processed);
		   if (processed == place2.length()){ // Full string is a number
			   type2 = (place2.find('.') != string::npos || place2.find('e') != string::npos || place2.find('E') != string::npos) ? TYPE_DOUBLE : TYPE_INT;
		   }
	   }
	   catch (...){} // Ignore if not a number


	   if (type1 == TYPE_UNKNOWN || type2 == TYPE_UNKNOWN) {
		   // This might happen if lookup failed or it's a literal not yet typed
		   // For now, assume error was already reported or handle literals
		   // Allow operations if one is unknown temporarily, but flag potential issue?
		   // Let's be strict: if either is unknown (and not handled literal), it's an error.
		   if (type1 == TYPE_UNKNOWN && place1.substr(0, 2) != "TB" && place1.substr(0, 1) != "T"){} // Could be literal okay?
		   else if (type2 == TYPE_UNKNOWN && place2.substr(0, 2) != "TB" && place2.substr(0, 1) != "T"){} // Could be literal okay?
		   else if (type1 == TYPE_UNKNOWN || type2 == TYPE_UNKNOWN){
			   cerr << "Syntax Error" << endl; exit(0); // Type error (unknown type)
			   return false;
		   }
	   }

	   // Type checking rules based on the operation
	   if (operation == "==" || operation == "!=" || operation == "<" || operation == "<=" || operation == ">" || operation == ">=") {
		   // Relational/Equality: Operands must be the same type
		   if (type1 != type2) {
			   cerr << "Syntax Error" << endl; exit(0); // Type mismatch for relational op
			   return false;
		   }
	   }
	   else if (operation == "+" || operation == "-" || operation == "*" || operation == "/") {
		   // Arithmetic: Operands must be the same type
		   if (type1 != type2) {
			   cerr << "Syntax Error" << endl; exit(0); // Type mismatch for arithmetic op
			   return false;
		   }
	   }
	   else if (operation == "&&" || operation == "||" || operation == "!") {
		   // Logical: Operands must be int (assuming 0=false, non-zero=true interpretation)
		   if (type1 != TYPE_INT || (type2 != TYPE_INT && operation != "!")) { // Type2 check only needed for binary ops
			   cerr << "Syntax Error" << endl; exit(0); // Type mismatch for logical op
			   return false;
		   }
	   }
	   else if (operation == "=") {
		   // Assignment: RHS type must be compatible with LHS type (allow int to double)
		   if (result == "")
		   {
			   cerr << "Syntax Error" << endl; exit(0); // Incompatible assignment
			   return false;
		   }
		   VarType lhsType = symbolTable.getTypeFromPlace(result); // 'result' holds LHS place in assignment gen
		   VarType rhsType = type1; // Arg1 holds RHS place/literal
		   if (lhsType == TYPE_UNKNOWN) return false; // LHS must exist
		   if (lhsType != rhsType && !(lhsType == TYPE_DOUBLE && rhsType == TYPE_INT)) {
			   cerr << "Syntax Error" << endl; exit(0); // Incompatible assignment
			   return false;
		   }
	   }
	   // Add checks for other ops (jumps, R, W) if needed, though jumps usually handle this via B exprs

	   return true; // Types are compatible
   }


   // Helper to find terminal Symbol object by name
   Symbol Grammar::findTerminalSymbol(const string& name) const {
	   for (const auto& t : terminals) {
		   if (t.name == name) {
			   return t;
		   }
	   }
	   // Special case for EOF
	   if (name == "$") return{ "$", TERMINAL };
	   return{ "", TERMINAL }; // Not found
   }
   // Helper to find non-terminal Symbol object by name
   Symbol Grammar::findNonTerminalSymbol(const string& name) const {
	   for (const auto& nt : nonTerminals) {
		   if (nt.name == name) {
			   return nt;
		   }
	   }
	   return{ "", NON_TERMINAL }; // Not found
   }


   // The main parsing function
   bool Grammar::parse(Lexer& lexer, const LR1ParsingTable& table) {
	   stack<int> stateStack;
	   stack<Symbol> symbolStack; // Stack for grammar symbols
	   // attributeStack is now a member variable

	   stateStack.push(0); // Initial state
	   nxq = 0; // Reset quadruple counter
	   OFFSET = 0; // Reset offset counter
	   symbolTable = SymbolTable(); // Reset symbol table
	   quads.clear(); // Clear previous quads
	   attributeStack = stack<Attributes>(); // Clear attribute stack


	   lexer.lex(); // Run lexer
	   LexerResult lexResult = lexer.getResult();
	 //  lexResult.print();
	   if (lexResult.error != ErrorType::NONE) {
		   cout << "Syntax Error" << endl; exit(0); // Lexical error treated as Syntax Error
		   return false;
	   }

	   int tokenIndex = 0;
	   bool parsing = true;

	   while (parsing) {
		   int currentState = stateStack.top();
		   Token currentToken;
		   string currentTerminalName;

		   if (tokenIndex < lexResult.tokens.size()) {
			   currentToken = lexResult.tokens[tokenIndex];
			   currentTerminalName = mapTokenToTerminal(currentToken);
			   if (currentTerminalName == "") {
				   // Unrecognized token from lexer/mapper perspective
				   cout << "Syntax Error" << endl; exit(0);
				   return false;
			   }
		   }
		   else {
			   currentTerminalName = "$"; // End of input marker
		   }

		   Symbol currentTerminalSymbol = findTerminalSymbol(currentTerminalName);
		   if (currentTerminalSymbol.name == "" && currentTerminalName != "$"){
			   cout << "Syntax Error" << endl; exit(0); // Terminal not found in grammar
			   return false;
		   }


		   // Lookup action in table
		   Action action;
		   if (currentState < table.actionTable.size() &&
			   table.actionTable[currentState].count(currentTerminalSymbol)) {
			   action = table.actionTable[currentState].at(currentTerminalSymbol);
		   }
		   else {
			   action.type = ERROR; // No action defined
		   }

		   // --- Debugging Output (Optional) ---
		   // cout << "State: " << currentState << ", Token: " << currentTerminalName << " (" << currentToken.value << "), Action: " << action.toString() << endl;
		   // cout << "Symbol Stack: ";
		   // stack<Symbol> tempSym = symbolStack;
		   // vector<string> syms;
		   // while(!tempSym.empty()){ syms.push_back(tempSym.top().name); tempSym.pop();}
		   // reverse(syms.begin(), syms.end());
		   // for(const auto& s : syms) cout << s << " ";
		   // cout << endl;
		   // cout << "Attribute Stack Size: " << attributeStack.size() << endl;
		   // --- End Debugging Output ---


		   switch (action.type) {
		   case SHIFT: {
						   stateStack.push(action.target);
						   symbolStack.push(currentTerminalSymbol);

						   // Push attributes for the terminal onto attribute stack
						   Attributes termAttrs;
						   termAttrs.name = currentToken.value; // Store the actual lexeme
						   // Set type based on terminal name if needed (e.g., for UINT, UFLOAT)
						   if (currentTerminalName == "UINT") termAttrs.type = TYPE_INT;
						   else if (currentTerminalName == "UFLOAT") termAttrs.type = TYPE_DOUBLE;
						   else if (currentTerminalName == "id") termAttrs.type = TYPE_UNKNOWN; // Type resolved later by lookup

						   // Store operator for REL, PLUS_MINUS, MUL_DIV if needed directly
						   if (currentTerminalSymbol.name == "+" || currentTerminalSymbol.name == "-" ||
							   currentTerminalSymbol.name == "*" || currentTerminalSymbol.name == "/" ||
							   currentTerminalSymbol.name == "==" || currentTerminalSymbol.name == "!=" ||
							   currentTerminalSymbol.name == "<" || currentTerminalSymbol.name == "<=" ||
							   currentTerminalSymbol.name == ">" || currentTerminalSymbol.name == ">=") {
							   termAttrs.op = currentTerminalSymbol.name;
						   }


						   attributeStack.push(termAttrs);

						   tokenIndex++; // Consume token
						   break;
		   }
		   case REDUCE: {
							int productionIndex = action.target;
							if (productionIndex < 0 || productionIndex >= productions.size()) {
								cout << "Syntax Error" << endl; exit(0); // Invalid production index
								return false;
							}
							const Production& rule = productions[productionIndex];
							int rhsSize = rule.right.size();

							// Pop states and symbols, collect attributes
							vector<Attributes> rhsAttributes(rhsSize);
							vector<Symbol> rhsSymbolsPopped(rhsSize);
							for (int i = 0; i < rhsSize; ++i) {
								if (stateStack.empty() || symbolStack.empty() || attributeStack.empty()) {
									cout << "Syntax Error" << endl; exit(0); // Stack underflow
									return false;
								}
								stateStack.pop();
								// Store attributes before popping symbol/attribute stacks
								// The order matters: attributes correspond to symbols popped *in reverse*
								if (!attributeStack.empty()) { // Check prevents crash on empty ^ reduction
									rhsAttributes[rhsSize - 1 - i] = attributeStack.top();
									attributeStack.pop();
								}
								else if (rhsSize > 0) {
									// This case might occur for ^ -> reduction where rhsSize=0, which is fine
									// But if rhsSize > 0 and stack is empty, it's an error.
									cout << "Syntax Error" << endl; exit(0); // Attribute stack mismatch
									return false;
								}

								if (!symbolStack.empty()){
									rhsSymbolsPopped[rhsSize - 1 - i] = symbolStack.top();
									symbolStack.pop();
								}
								else if (rhsSize > 0){
									cout << "Syntax Error" << endl; exit(0); // Symbol stack mismatch
									return false;
								}
							}

							// --- Debugging reduce ---
							/* cout << "Reducing by: " << rule.toString() << endl;
							 for(int i = 0; i < rhsSize; ++i) {
							      cout << "  RHS[" << i << "]: " << rhsSymbolsPopped[i].name << " Attrs(name="<< rhsAttributes[i].name <<", place="<<rhsAttributes[i].place << ", type=" << rhsAttributes[i].type << ", op=" << rhsAttributes[i].op << ")" << endl;
							 }*/
							// ---

							// Execute semantic action (defined below)
							Attributes lhsAttributes; // Attributes for the resulting non-terminal
							bool semanticOk = executeSemanticAction(productionIndex, rhsAttributes, lhsAttributes);
							if (!semanticOk || symbolTable.errorOccurred) {
								// executeSemanticAction should print "Syntax Error" or return false
								// Also check symbolTable flag for errors during enter/lookup
								if (!symbolTable.errorOccurred) cout << "Syntax Error" << endl; exit(0); // Print if not already done
								return false;
							}


							// Push LHS symbol
							symbolStack.push(rule.left);
							attributeStack.push(lhsAttributes); // Push calculated attributes for LHS


							// GOTO
							int prevState = stateStack.top();
							int gotoState = -1;
							if (prevState < table.gotoTable.size() && table.gotoTable[prevState].count(rule.left)) {
								gotoState = table.gotoTable[prevState].at(rule.left);
							}

							if (gotoState == -1) {
								cout << "Syntax Error" << endl; exit(0); // No GOTO entry defined
								return false;
							}
							stateStack.push(gotoState);
							break;
		   }
		   case ACCEPT:
			   // Successful parse!
			   parsing = false;
			   // The final 'End' quad is generated during reduction of SUBPROG
			   break;
		   case ERROR:
		   default:
			   cout << "Syntax Error" << endl; exit(0);
			   return false; // Parsing error
		   }
	   }

	   // After successful parse loop exit
	   symbolTable.print();
	   printQuads();
	   cout << endl; // Add trailing newline for successful output

	   return true;
   }


   void Grammar::printQuads() const {
	   cout << quads.size() << endl;
	   for (int i = 0; i < quads.size(); ++i) {
		   cout << i << ": " << quads[i].toString();
		   if (i != quads.size()-1)cout << endl;
	   }
   }



   // Semantic Action Execution (needs to be carefully implemented based on rules)
   bool Grammar::executeSemanticAction(int productionIndex, const vector<Attributes>& rhsAttrs, Attributes& lhsAttrs) {
	   const Production& rule = productions[productionIndex];
	   string ruleStr = rule.toString(); // For matching rules

	   // Use productionIndex or ruleStr to determine which action to perform
	   // This is a large switch statement or if-else chain based on the grammar rules provided

	   // Example action for T -> int {T.type=int;T.width=4;} (Rule index might vary)
	   if (rule.left.name == "T" && !rule.right.empty() && rule.right[0].name == "int") {
		   lhsAttrs.type = TYPE_INT;
		   lhsAttrs.width = 4;
		   return true;
	   }
	   // Example action for T -> double {T.type=double;T.width=8;}
	   else if (rule.left.name == "T" && !rule.right.empty() && rule.right[0].name == "double") {
		   lhsAttrs.type = TYPE_DOUBLE;
		   lhsAttrs.width = 8;
		   return true;
	   }
	   // Example action for ID -> id {ID.name=id}
	   else if (rule.left.name == "ID" && !rule.right.empty() && rule.right[0].name == "id") {
		   lhsAttrs.name = rhsAttrs[0].name; // Get name from terminal 'id'
		   return true;
	   }
	   // Example action for VARIABLE -> T ID {enter(...); ...}
	   else if (rule.left.name == "VARIABLE" && rule.right.size() == 2 && rule.right[0].name == "T" && rule.right[1].name == "ID") {
		   const Attributes& T_attrs = rhsAttrs[0];
		   const Attributes& ID_attrs = rhsAttrs[1];
		   int index = symbolTable.addEntry(ID_attrs.name, T_attrs.type);
		   if (index == -1) return false; // Error handled in addEntry

		   lhsAttrs.type = T_attrs.type;
		   lhsAttrs.width = T_attrs.width; // Propagate width
		   // ID_attrs.name should contain the actual identifier string
		   // T_attrs.type and T_attrs.width should hold info from T -> int/double
		   return true;
	   }
	   // Example: VARIABLE -> VARIABLE_1 , ID
	   else if (rule.left.name == "VARIABLE" && rule.right.size() == 3 && rule.right[0].name == "VARIABLE" && rule.right[1].name == "," && rule.right[2].name == "ID") {
		   const Attributes& VAR1_attrs = rhsAttrs[0];
		   const Attributes& ID_attrs = rhsAttrs[2];
		   int index = symbolTable.addEntry(ID_attrs.name, VAR1_attrs.type);
		   if (index == -1) return false;

		   lhsAttrs.type = VAR1_attrs.type; // Inherit type from previous VARIABLE
		   lhsAttrs.width = VAR1_attrs.width; // Inherit width
		   return true;
	   }
	   // Example: M -> ^ {OFFSET=0}
	   else if (rule.left.name == "M" && rule.right.empty()) {
		   OFFSET = 0; // Initialize global offset
		   // M doesn't produce attributes needed later? Check grammar. If so, set them.
		   lhsAttrs.quad = nxq; // M might mark start of decls, store current quad index? No, M rule is simple.
		   return true;
	   }
	   // Example: N -> ^ {N.quad=nxq}
	   else if (rule.left.name == "N" && rule.right.empty()) {
		   lhsAttrs.quad = nxq; // Store current quad index for backpatching jumps
		   return true;
	   }
	   // Example: ASSIGN -> ID = EXPR {p=lookup(ID.name); gen(=, EXPR.place, -, p)}
	   else if (rule.left.name == "ASSIGN" && rule.right.size() == 3 && rule.right[0].name == "ID" && rule.right[1].name == "=" && rule.right[2].name == "EXPR") {
		   const Attributes& id_attrs = rhsAttrs[0];
		   const Attributes& expr_attrs = rhsAttrs[2];
		   string lhs_place = symbolTable.lookupPlace(id_attrs.name);
		   if (lhs_place == "") return false; // Undefined variable

		   // Type check for assignment
		   if (!checkTypes(expr_attrs.place, "", "=", lhs_place)) return false;

		   gen("=", expr_attrs.place, "-", lhs_place);
		   // ASSIGN doesn't seem to produce attributes, but STATEMENT needs nextlist
		   // We handle STATEMENT -> ASSIGN separately below.
		   return true;
	   }
	   // Example: FACTOR -> ID {FACTOR.place=lookup(ID.name); FACTOR.type=lookup_type(ID.name)}
	   else if (rule.left.name == "FACTOR" && rule.right.size() == 1 && rule.right[0].name == "ID") {
		   const Attributes& id_attrs = rhsAttrs[0];
		   lhsAttrs.place = symbolTable.lookupPlace(id_attrs.name);
		   if (lhsAttrs.place == "") return false; // Undefined variable
		   lhsAttrs.type = symbolTable.lookupType(id_attrs.name);
		   if (lhsAttrs.type == TYPE_UNKNOWN) return false; // Should not happen if lookupPlace succeeded
		   lhsAttrs.name = id_attrs.name; // Keep name if needed
		   return true;
	   }
	   // Example: FACTOR -> UINT {FACTOR.place=newtemp(int); FACTOR.type=int; gen(=,UINT,-,FACTOR.place)}
	   else if (rule.left.name == "FACTOR" && rule.right.size() == 1 && rule.right[0].name == "UINT") {
		   const Attributes& uint_attrs = rhsAttrs[0]; // Contains the integer string in .name
		   lhsAttrs.type = TYPE_INT;
		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);
		   gen("=", uint_attrs.name, "-", lhsAttrs.place);
		   return true;
	   }
	   // Example: FACTOR -> UFLOAT {FACTOR.place=newtemp(double); FACTOR.type=double; gen(=,UFLOAT,-,FACTOR.place)}
	   else if (rule.left.name == "FACTOR" && rule.right.size() == 1 && rule.right[0].name == "UFLOAT") {
		   const Attributes& ufloat_attrs = rhsAttrs[0]; // Contains the float string in .name
		   lhsAttrs.type = TYPE_DOUBLE;
		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);
		   gen("=", ufloat_attrs.name, "-", lhsAttrs.place); // gen handles formatting
		   return true;
	   }
	   // Example: FACTOR -> ( EXPR ) {FACTOR.place=EXPR.place; FACTOR.type=EXPR.type}
	   else if (rule.left.name == "FACTOR" && rule.right.size() == 3 && rule.right[0].name == "(" && rule.right[1].name == "EXPR" && rule.right[2].name == ")") {
		   lhsAttrs.place = rhsAttrs[1].place;
		   lhsAttrs.type = rhsAttrs[1].type;
		   return true;
	   }
	   // Example: PLUS_MINUS -> + {PLUS_MINUS.op='+'}
	   else if (rule.left.name == "PLUS_MINUS" && rule.right.size() == 1 && rule.right[0].name == "+") {
		   lhsAttrs.op = "+";
		   return true;
	   }
	   // Example: PLUS_MINUS -> - {PLUS_MINUS.op='-'}
	   else if (rule.left.name == "PLUS_MINUS" && rule.right.size() == 1 && rule.right[0].name == "-") {
		   lhsAttrs.op = "-";
		   return true;
	   }
	   // Example: FACTOR -> PLUS_MINUS FACTOR_1 {FACTOR.place=newtemp(FACTOR_1.type);...gen(op,0,FACTOR_1.place,FACTOR.place)}
	   else if (rule.left.name == "FACTOR" && rule.right.size() == 2 && rule.right[0].name == "PLUS_MINUS" && rule.right[1].name == "FACTOR") {
		   const Attributes& op_attrs = rhsAttrs[0];
		   const Attributes& factor1_attrs = rhsAttrs[1];
		   lhsAttrs.type = factor1_attrs.type; // Result type is same as operand
		   if (lhsAttrs.type == TYPE_UNKNOWN) return false; // Need type info
		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);

		   // Type check (unary op, arg1 is 0) - checkTypes handles "0" pseudo-arg
		   if (!checkTypes("0", factor1_attrs.place, "unary" + op_attrs.op)) return false;

		   gen(op_attrs.op, "0", factor1_attrs.place, lhsAttrs.place);
		   return true;
	   }
	   // Example: ITEM -> FACTOR {ITEM.place = FACTOR.place; ITEM.type = FACTOR.type}
	   else if (rule.left.name == "ITEM" && rule.right.size() == 1 && rule.right[0].name == "FACTOR") {
		   lhsAttrs.place = rhsAttrs[0].place;
		   lhsAttrs.type = rhsAttrs[0].type;
		   return true;
	   }
	   // Example: MUL_DIV -> * /
	   else if (rule.left.name == "MUL_DIV" && rule.right.size() == 1 && rule.right[0].name == "*") {
		   lhsAttrs.op = "*"; return true;
	   }
	   else if (rule.left.name == "MUL_DIV" && rule.right.size() == 1 && rule.right[0].name == "/") {
		   lhsAttrs.op = "/"; return true;
	   }
	   // Example: ITEM -> ITEM_1 MUL_DIV FACTOR {ITEM.place=newtemp(FACTOR.type); ... gen(op, ITEM_1.place, FACTOR.place, ITEM.place)}
	   else if (rule.left.name == "ITEM" && rule.right.size() == 3 && rule.right[0].name == "ITEM" && rule.right[1].name == "MUL_DIV" && rule.right[2].name == "FACTOR") {
		   const Attributes& item1_attrs = rhsAttrs[0];
		   const Attributes& op_attrs = rhsAttrs[1];
		   const Attributes& factor_attrs = rhsAttrs[2];

		   // Determine result type (should match operands)
		   /*lhsAttrs.type = item1_attrs.type | factor_attrs.type*/; // Or factor_attrs.type, they must match
		   
		   if (item1_attrs.type == TYPE_INT || factor_attrs.type == TYPE_INT)
			   lhsAttrs.type = TYPE_INT;
		   else if (item1_attrs.type == TYPE_DOUBLE || factor_attrs.type == TYPE_DOUBLE)
			   lhsAttrs.type = TYPE_DOUBLE;
		   else
			   lhsAttrs.type = TYPE_UNKNOWN; // Unknown type, need to check
		   if (lhsAttrs.type == TYPE_UNKNOWN) return false; // Need type info

		   // Type check
		   if (!checkTypes(item1_attrs.place, factor_attrs.place, op_attrs.op)) return false;


		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);
		   gen(op_attrs.op, item1_attrs.place, factor_attrs.place, lhsAttrs.place);
		   return true;
	   }
	   // Example: RELITEM -> ITEM
	   else if (rule.left.name == "RELITEM" && rule.right.size() == 1 && rule.right[0].name == "ITEM") {
		   lhsAttrs.place = rhsAttrs[0].place;
		   lhsAttrs.type = rhsAttrs[0].type;
		   return true;
	   }
	   // Example: RELITEM -> RELITEM_1 PLUS_MINUS ITEM
	   else if (rule.left.name == "RELITEM" && rule.right.size() == 3 && rule.right[0].name == "RELITEM" && rule.right[1].name == "PLUS_MINUS" && rule.right[2].name == "ITEM") {
		   const Attributes& relitem1_attrs = rhsAttrs[0];
		   const Attributes& op_attrs = rhsAttrs[1];
		   const Attributes& item_attrs = rhsAttrs[2];

		   lhsAttrs.type = relitem1_attrs.type; // Result type matches operands
		   if (lhsAttrs.type == TYPE_UNKNOWN) return false;

		   // Type check
		   if (!checkTypes(relitem1_attrs.place, item_attrs.place, op_attrs.op)) return false;


		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);
		   gen(op_attrs.op, relitem1_attrs.place, item_attrs.place, lhsAttrs.place);
		   return true;
	   }
	   // Example: NOITEM -> RELITEM
	   else if (rule.left.name == "NOITEM" && rule.right.size() == 1 && rule.right[0].name == "RELITEM") {
		   lhsAttrs.place = rhsAttrs[0].place;
		   lhsAttrs.type = rhsAttrs[0].type;
		   return true;
	   }
	   // Example: REL -> ==, !=, <, <=, >, >=
	   else if (rule.left.name == "REL") {
		   lhsAttrs.op = rhsAttrs[0].name; // The operator itself
		   return true;
	   }
	   // Example: NOITEM -> NOITEM_1 REL RELITEM {NOITEM.place=newtemp(int); ... gen(REL.op, NOITEM_1.place, RELITEM.place, NOITEM.place)}
	   else if (rule.left.name == "NOITEM" && rule.right.size() == 3 && rule.right[0].name == "NOITEM" && rule.right[1].name == "REL" && rule.right[2].name == "RELITEM") {
		   const Attributes& noitem1_attrs = rhsAttrs[0];
		   const Attributes& rel_attrs = rhsAttrs[1];
		   const Attributes& relitem_attrs = rhsAttrs[2];

		   lhsAttrs.type = TYPE_INT; // Result of a relation is boolean (int)
		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);

		   // Type check for relational op
		   if (!checkTypes(noitem1_attrs.place, relitem_attrs.place, rel_attrs.op)) return false;


		   gen(rel_attrs.op, noitem1_attrs.place, relitem_attrs.place, lhsAttrs.place);
		   return true;
	   }
	   // Example: ANDITEM -> NOITEM
	   else if (rule.left.name == "ANDITEM" && rule.right.size() == 1 && rule.right[0].name == "NOITEM") {
		   lhsAttrs.place = rhsAttrs[0].place;
		   lhsAttrs.type = rhsAttrs[0].type;
		   return true;
	   }
	   // Example: ANDITEM -> ! NOITEM {ANDITEM=newtemp(int); ... gen(!, NOITEM.place, -, ANDITEM.place)}
	   else if (rule.left.name == "ANDITEM" && rule.right.size() == 2 && rule.right[0].name == "!" && rule.right[1].name == "NOITEM") {
		   const Attributes& noitem_attrs = rhsAttrs[1];

		   lhsAttrs.type = TYPE_INT; // Result of logical NOT is int
		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);

		   // Type check for logical NOT (operand must be int)
		   if (!checkTypes(noitem_attrs.place, "-", "!")) return false;

		   gen("!", noitem_attrs.place, "-", lhsAttrs.place);
		   return true;
	   }
	   // Example: ORITEM -> ANDITEM
	   else if (rule.left.name == "ORITEM" && rule.right.size() == 1 && rule.right[0].name == "ANDITEM") {
		   lhsAttrs.place = rhsAttrs[0].place;
		   lhsAttrs.type = rhsAttrs[0].type;
		   return true;
	   }
	   // Example: ORITEM -> ORITEM_1 && ANDITEM {ORITEM.place=newtemp(int); ... gen(&&, ORITEM_1.place, ANDITEM.place, ORITEM.place)}
	   else if (rule.left.name == "ORITEM" && rule.right.size() == 3 && rule.right[0].name == "ORITEM" && rule.right[1].name == "&&" && rule.right[2].name == "ANDITEM") {
		   const Attributes& oritem1_attrs = rhsAttrs[0];
		   const Attributes& anditem_attrs = rhsAttrs[2];

		   lhsAttrs.type = TYPE_INT; // Result of && is int
		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);

		   // Type check (operands must be int)
		   if (!checkTypes(oritem1_attrs.place, anditem_attrs.place, "&&")) return false;

		   gen("&&", oritem1_attrs.place, anditem_attrs.place, lhsAttrs.place);
		   return true;
	   }
	   // Example: EXPR -> ORITEM
	   else if (rule.left.name == "EXPR" && rule.right.size() == 1 && rule.right[0].name == "ORITEM") {
		   lhsAttrs.place = rhsAttrs[0].place;
		   lhsAttrs.type = rhsAttrs[0].type;
		   return true;
	   }
	   // Example: EXPR -> EXPR_1 || ORITEM {EXPR.place=newtemp(int); ... gen(||, EXPR_1.place, ORITEM.place, EXPR.place)}
	   else if (rule.left.name == "EXPR" && rule.right.size() == 3 && rule.right[0].name == "EXPR" && rule.right[1].name == "||" && rule.right[2].name == "ORITEM") {
		   const Attributes& expr1_attrs = rhsAttrs[0];
		   const Attributes& oritem_attrs = rhsAttrs[2];

		   lhsAttrs.type = TYPE_INT; // Result of || is int
		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);

		   // Type check (operands must be int)
		   if (!checkTypes(expr1_attrs.place, oritem_attrs.place, "||")) return false;

		   gen("||", expr1_attrs.place, oritem_attrs.place, lhsAttrs.place);
		   return true;
	   }
	   // --- Boolean Expressions (B, BORTERM, BANDTERM) ---
	   // BFACTOR -> ID {BFACTOR.place=lookup(ID.name); BFACTOR.type=lookup_type(ID.name)}
	   else if (rule.left.name == "BFACTOR" && rule.right.size() == 1 && rule.right[0].name == "id") { // Corrected: Uses ID non-terminal which reduces from id
		   // This action seems duplicated/incorrect in the prompt. Assuming it should reduce from ID non-terminal
		   // Let's assume the correct reduction is BFACTOR -> ID based on context
		   // Need grammar rule BFACTOR -> ID { BFACTOR.place=lookup(ID.name); ... }
		   // Let's modify the check:
		   cout << "Syntax Error" << endl; exit(0); // Grammar mismatch
		   return false; // Remove this error if BFACTOR -> ID is added to grammar file
	   }
	   else if (rule.left.name == "BFACTOR" && rule.right.size() == 1 && rule.right[0].name == "ID") { // Correct version if ID reduces from id
		   const Attributes& id_attrs = rhsAttrs[0];
		   lhsAttrs.place = symbolTable.lookupPlace(id_attrs.name);
		   if (lhsAttrs.place == "") return false;
		   lhsAttrs.type = symbolTable.lookupType(id_attrs.name);
		   if (lhsAttrs.type == TYPE_UNKNOWN) return false;
		   return true;
	   }

	   // BFACTOR -> UINT {BFACTOR.place=newtemp(int);...gen(=,UINT,-,BFACTOR.place)} - Note: prompt uses FACTOR.place, assume BFACTOR.place
	   else if (rule.left.name == "BFACTOR" && rule.right.size() == 1 && rule.right[0].name == "UINT") {
		   const Attributes& uint_attrs = rhsAttrs[0];
		   lhsAttrs.type = TYPE_INT;
		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);
		   gen("=", uint_attrs.name, "-", lhsAttrs.place); // Corrected target
		   return true;
	   }
	   // BFACTOR -> UFLOAT {BFACTOR.place=newtemp(double);...gen(=,UFLOAT,-,BFACTOR.place)}
	   else if (rule.left.name == "BFACTOR" && rule.right.size() == 1 && rule.right[0].name == "UFLOAT") {
		   const Attributes& ufloat_attrs = rhsAttrs[0];
		   lhsAttrs.type = TYPE_DOUBLE;
		   lhsAttrs.place = symbolTable.newTemp(lhsAttrs.type);
		   gen("=", ufloat_attrs.name, "-", lhsAttrs.place);
		   return true;
	   }
	   // BANDTERM -> BFACTOR {BANDTERM.truelist=mklist(nxq); BANDTERM.falselist=mklist(nxq+1); gen(jnz,BFACTOR.place,-,0); gen(j,-,-,0)}
	   else if (rule.left.name == "BANDTERM" && rule.right.size() == 1 && rule.right[0].name == "BFACTOR") {
		   const Attributes& bfactor_attrs = rhsAttrs[0];
		   // Need type check? BFACTOR should be int/bool ideally. Prompt doesn't specify.
		   // Let's assume any non-zero value is true for jnz.
		   if (bfactor_attrs.place == "") return false; // Need a place to test

		   lhsAttrs.truelist = mklist(nxq);
		   lhsAttrs.falselist = mklist(nxq + 1);
		   gen("jnz", bfactor_attrs.place, "-", "0"); // Jump if true (non-zero)
		   gen("j", "-", "-", "0");                 // Jump if false (zero)
		   return true;
	   }
	   // BANDTERM -> BFACTOR_1 REL BFACTOR_2 {BANDTERM.truelist=mklist(nxq); ... gen(j+REL.op,...); gen(j,...)}
	   else if (rule.left.name == "BANDTERM" && rule.right.size() == 3 && rule.right[0].name == "BFACTOR" && rule.right[1].name == "REL" && rule.right[2].name == "BFACTOR") {
		   const Attributes& bfactor1_attrs = rhsAttrs[0];
		   const Attributes& rel_attrs = rhsAttrs[1];
		   const Attributes& bfactor2_attrs = rhsAttrs[2];

		   // Type check for relational op
		   if (!checkTypes(bfactor1_attrs.place, bfactor2_attrs.place, rel_attrs.op)) return false;


		   lhsAttrs.truelist = mklist(nxq);
		   lhsAttrs.falselist = mklist(nxq + 1);
		   gen("j" + rel_attrs.op, bfactor1_attrs.place, bfactor2_attrs.place, "0"); // Conditional jump on true
		   gen("j", "-", "-", "0"); // Unconditional jump on false
		   return true;
	   }
	   // BANDTERM -> ! BANDTERM_1 {BANDTERM.truelist=BANDTERM_1.falselist; BANDTERM.falselist=BANDTERM_1.truelist}
	   else if (rule.left.name == "BANDTERM" && rule.right.size() == 2 && rule.right[0].name == "!" && rule.right[1].name == "BANDTERM") {
		   lhsAttrs.truelist = rhsAttrs[1].falselist; // Swap lists for NOT
		   lhsAttrs.falselist = rhsAttrs[1].truelist;
		   return true;
	   }
	   // BANDTERM -> ( B ) {BANDTERM.truelist=B.truelist; BANDTERM.falselist=B.falselist}
	   else if (rule.left.name == "BANDTERM" && rule.right.size() == 3 && rule.right[0].name == "(" && rule.right[1].name == "B" && rule.right[2].name == ")") {
		   lhsAttrs.truelist = rhsAttrs[1].truelist;
		   lhsAttrs.falselist = rhsAttrs[1].falselist;
		   return true;
	   }
	   // BORTERM -> BANDTERM {BORTERM.truelist=BANDTERM.truelist; BORTERM.falselist=BANDTERM.falselist}
	   else if (rule.left.name == "BORTERM" && rule.right.size() == 1 && rule.right[0].name == "BANDTERM") {
		   lhsAttrs.truelist = rhsAttrs[0].truelist;
		   lhsAttrs.falselist = rhsAttrs[0].falselist;
		   return true;
	   }
	   // BORTERM -> BORTERM_1 && N BANDTERM {backpatch(BORTERM_1.truelist, N.quad); ...}
	   else if (rule.left.name == "BORTERM" && rule.right.size() == 4 && rule.right[0].name == "BORTERM" && rule.right[1].name == "&&" && rule.right[2].name == "N" && rule.right[3].name == "BANDTERM") {
		   const Attributes& borterm1_attrs = rhsAttrs[0];
		   const Attributes& n_attrs = rhsAttrs[2];
		   const Attributes& bandterm_attrs = rhsAttrs[3];

		   backpatch(borterm1_attrs.truelist, n_attrs.quad); // If BORTERM1 is true, jump to start of BANDTERM
		   lhsAttrs.truelist = bandterm_attrs.truelist; // True exit is from BANDTERM
		   lhsAttrs.falselist = merge(borterm1_attrs.falselist, bandterm_attrs.falselist); // False exit is from either
		   return true;
	   }
	   // B -> BORTERM {B.truelist=BORTERM.truelist; B.falselist=BORTERM.falselist}
	   else if (rule.left.name == "B" && rule.right.size() == 1 && rule.right[0].name == "BORTERM") {
		   lhsAttrs.truelist = rhsAttrs[0].truelist;
		   lhsAttrs.falselist = rhsAttrs[0].falselist;
		   return true;
	   }
	   // B -> B_1 || N BORTERM {backpatch(B_1.falselist, N.quad); ...}
	   else if (rule.left.name == "B" && rule.right.size() == 4 && rule.right[0].name == "B" && rule.right[1].name == "||" && rule.right[2].name == "N" && rule.right[3].name == "BORTERM") {
		   const Attributes& b1_attrs = rhsAttrs[0];
		   const Attributes& n_attrs = rhsAttrs[2];
		   const Attributes& borterm_attrs = rhsAttrs[3];

		   backpatch(b1_attrs.falselist, n_attrs.quad); // If B1 is false, jump to start of BORTERM
		   lhsAttrs.truelist = merge(b1_attrs.truelist, borterm_attrs.truelist); // True exit is from either
		   lhsAttrs.falselist = borterm_attrs.falselist; // False exit is only from BORTERM
		   return true;
	   }
	   // --- Statements (STATEMENT, L) ---
	   // STATEMENT -> ^ {STATEMENT.nextlist=mklist()}
	   else if (rule.left.name == "STATEMENT" && rule.right.empty()) {
		   lhsAttrs.nextlist = mklist(); // Empty statement has empty next list
		   return true;
	   }
	   // STATEMENT -> ASSIGN {STATEMENT.nextlist=mklist()}
	   else if (rule.left.name == "STATEMENT" && rule.right.size() == 1 && rule.right[0].name == "ASSIGN") {
		   lhsAttrs.nextlist = mklist(); // Assignment doesn't inherently jump, empty nextlist
		   return true;
	   }
	   // STATEMENT -> { L ; } {STATEMENT.nextlist=L.nextlist}
	   else if (rule.left.name == "STATEMENT" && rule.right.size() == 4 && rule.right[0].name == "{" && rule.right[1].name == "L" && rule.right[2].name == ";" && rule.right[3].name == "}") {
		   lhsAttrs.nextlist = rhsAttrs[1].nextlist; // Compound statement inherits nextlist from last statement in L
		   return true;
	   }
	   // L -> STATEMENT {L.nextlist=STATEMENT.nextlist}
	   else if (rule.left.name == "L" && rule.right.size() == 1 && rule.right[0].name == "STATEMENT") {
		   lhsAttrs.nextlist = rhsAttrs[0].nextlist;
		   return true;
	   }
	   // L -> L_1 ; N STATEMENT {backpatch(L1.nextlist, N.quad); L.nextlist=STATEMENT.nextlist}
	   else if (rule.left.name == "L" && rule.right.size() == 4 && rule.right[0].name == "L" && rule.right[1].name == ";" && rule.right[2].name == "N" && rule.right[3].name == "STATEMENT") {
		   const Attributes& l1_attrs = rhsAttrs[0];
		   const Attributes& n_attrs = rhsAttrs[2];
		   const Attributes& stmt_attrs = rhsAttrs[3];

		   backpatch(l1_attrs.nextlist, n_attrs.quad); // Patch jumps from L1 to start of STATEMENT
		   lhsAttrs.nextlist = stmt_attrs.nextlist; // Overall nextlist is from the last STATEMENT
		   return true;
	   }
	   // STATEMENT -> if B then N STATEMENT_1 {backpatch(B.truelist, N.quad); STATEMENT.nextlist=merge(B.falselist, STATEMENT_1.nextlist)}
	   else if (rule.left.name == "STATEMENT" && rule.right.size() == 5 && rule.right[0].name == "if" && rule.right[1].name == "B" && rule.right[2].name == "then" && rule.right[3].name == "N" && rule.right[4].name == "STATEMENT") {
		   const Attributes& b_attrs = rhsAttrs[1];
		   const Attributes& n_attrs = rhsAttrs[3];
		   const Attributes& stmt1_attrs = rhsAttrs[4];

		   backpatch(b_attrs.truelist, n_attrs.quad); // If B is true, jump to start of STATEMENT1
		   lhsAttrs.nextlist = merge(b_attrs.falselist, stmt1_attrs.nextlist); // Next is jump from B false or jump from end of STATEMENT1
		   return true;
	   }
	   // STATEMENT -> while N_1 B do N_2 STATEMENT_1 {...; gen(j,-,-,N_1.quad)}
	   else if (rule.left.name == "STATEMENT" && rule.right.size() == 6 && rule.right[0].name == "while" && rule.right[1].name == "N" && rule.right[2].name == "B" && rule.right[3].name == "do" && rule.right[4].name == "N" && rule.right[5].name == "STATEMENT") {
		   const Attributes& n1_attrs = rhsAttrs[1]; // Quad before B
		   const Attributes& b_attrs = rhsAttrs[2];
		   const Attributes& n2_attrs = rhsAttrs[4]; // Quad before STATEMENT1
		   const Attributes& stmt1_attrs = rhsAttrs[5];

		   backpatch(b_attrs.truelist, n2_attrs.quad);       // If B is true, jump to start of loop body (STATEMENT1)
		   backpatch(stmt1_attrs.nextlist, n1_attrs.quad);   // Jump from end of loop body back to test (before B)
		   lhsAttrs.nextlist = b_attrs.falselist;             // If B is false, exit loop (this is the overall nextlist)
		   gen("j", "-", "-", to_string(n1_attrs.quad));   // Jump from end of loop structure back to test
		   return true;
	   }
	   // --- SCANF/PRINTF ---
	   // SCANF_BEGIN -> scanf ( ID {p=lookup(ID.name); gen(R,-,-,p)}
	   else if (rule.left.name == "SCANF_BEGIN" && rule.right.size() == 3 && rule.right[0].name == "scanf" && rule.right[1].name == "(" && rule.right[2].name == "ID") {
		   const Attributes& id_attrs = rhsAttrs[2];
		   string place = symbolTable.lookupPlace(id_attrs.name);
		   if (place == "") return false;
		   gen("R", "-", "-", place);
		   // SCANF_BEGIN doesn't seem to need attributes itself
		   return true;
	   }
	   // SCANF_BEGIN -> SCANF_BEGIN , ID {p=lookup(ID.name); gen(R,-,-,p)}
	   else if (rule.left.name == "SCANF_BEGIN" && rule.right.size() == 3 && rule.right[0].name == "SCANF_BEGIN" && rule.right[1].name == "," && rule.right[2].name == "ID") {
		   const Attributes& id_attrs = rhsAttrs[2];
		   string place = symbolTable.lookupPlace(id_attrs.name);
		   if (place == "") return false;
		   gen("R", "-", "-", place);
		   return true;
	   }
	   // SCANF -> SCANF_BEGIN ) {}
	   else if (rule.left.name == "SCANF" && rule.right.size() == 2 && rule.right[0].name == "SCANF_BEGIN" && rule.right[1].name == ")") {
		   // No specific action needed here, handled by SCANF_BEGIN
		   return true;
	   }
	   // STATEMENT -> SCANF {STATEMENT.nextlist=mklist()}
	   else if (rule.left.name == "STATEMENT" && rule.right.size() == 1 && rule.right[0].name == "SCANF") {
		   lhsAttrs.nextlist = mklist(); // SCANF doesn't jump
		   return true;
	   }
	   // PRINTF_BEGIN -> printf ( ID {p=lookup(ID.name); gen(W,-,-,p)}
	   else if (rule.left.name == "PRINTF_BEGIN" && rule.right.size() == 3 && rule.right[0].name == "printf" && rule.right[1].name == "(" && rule.right[2].name == "ID") {
		   const Attributes& id_attrs = rhsAttrs[2];
		   string place = symbolTable.lookupPlace(id_attrs.name);
		   if (place == "") return false;
		   gen("W", "-", "-", place);
		   return true;
	   }
	   // PRINTF_BEGIN -> PRINTF_BEGIN , ID {p=lookup(ID.name); gen(W,-,-,p)}
	   else if (rule.left.name == "PRINTF_BEGIN" && rule.right.size() == 3 && rule.right[0].name == "PRINTF_BEGIN" && rule.right[1].name == "," && rule.right[2].name == "ID") {
		   const Attributes& id_attrs = rhsAttrs[2];
		   string place = symbolTable.lookupPlace(id_attrs.name);
		   if (place == "") return false;
		   gen("W", "-", "-", place);
		   return true;
	   }
	   // PRINTF -> PRINTF_BEGIN ) {}
	   else if (rule.left.name == "PRINTF" && rule.right.size() == 2 && rule.right[0].name == "PRINTF_BEGIN" && rule.right[1].name == ")") {
		   // No specific action needed here
		   return true;
	   }
	   // STATEMENT -> PRINTF {STATEMENT.nextlist=mklist()}
	   else if (rule.left.name == "STATEMENT" && rule.right.size() == 1 && rule.right[0].name == "PRINTF") {
		   lhsAttrs.nextlist = mklist(); // PRINTF doesn't jump
		   return true;
	   }
	   // --- Program Structure ---
	   // VARIABLES -> VARIABLE ; {}
	   // VARIABLES -> VARIABLES VARIABLE ; {}
	   else if (rule.left.name == "VARIABLES") {
		   // These rules mainly structure declarations, actions are in VARIABLE reduction
		   return true;
	   }
	   // SUBPROG -> M VARIABLES STATEMENT {backpatch(STATEMENT.nextlist, nxq); gen(End,-,-,-)}
	   else if (rule.left.name == "SUBPROG") {
		   // M reduction already set OFFSET=0
		   // VARIABLES reduction handled declarations
		   // STATEMENT reduction created code and nextlist
		   const Attributes& stmt_attrs = rhsAttrs[2];
		   backpatch(stmt_attrs.nextlist, nxq); // Patch any remaining jumps from statement block
		   gen("End", "-", "-", "-");
		   return true;
	   }
	   // PROG -> SUBPROG {}
	   else if (rule.left.name == "PROG'") { // Handle augmented grammar start symbol reduction
		   // This is usually the accept point, handled by the main loop's ACCEPT case
		   return true;
	   }
	   else if (rule.left.name == "PROG"){ // The original start symbol
		   // No action needed here, just structure
		   return true;
	   }

	   exit(1);
	   // If no rule matched, it's an internal error or unhandled production
	   cerr << "Internal Error: Unhandled reduction rule: " << rule.toString() << " (Index: " << productionIndex << ")" << endl;
	   return false; // Indicate failure
   }

   

   // 序列化转移关系
   void Grammar::serializeTransitions(ofstream& out) const {
	   // 序列化终结符转移
	   out << "TERMINAL_TRANSITIONS\n";
	   for (const auto& entry : transitions) {
		   out << entry.first.first << "\t"
			   << entry.first.second.serialize() << "\t"
			   << entry.second << "\n";
	   }
	   out << "TERMINAL_TRANSITIONS_END\n";

	   // 序列化非终结符转移
	   out << "NON_TERMINAL_TRANSITIONS\n";
	   for (const auto& entry : nonTerminalTransitions) {
		   out << entry.first.first << "\t"
			   << entry.first.second.serialize() << "\t"
			   << entry.second << "\n";
	   }
	   out << "NON_TERMINAL_TRANSITIONS_END\n";
   }

   // 反序列化转移关系
   void Grammar::deserializeTransitions(ifstream& in) {
	   string line;
	   string section;

	   while (getline(in, line)) {
		   if (line == "TERMINAL_TRANSITIONS") {
			   section = "TERMINAL";
			   continue;
		   }
		   else if (line == "TERMINAL_TRANSITIONS_END") {
			   section = "";
			   continue;
		   }
		   else if (line == "NON_TERMINAL_TRANSITIONS") {
			   section = "NON_TERMINAL";
			   continue;
		   }
		   else if (line == "NON_TERMINAL_TRANSITIONS_END") {
			   break;
		   }

		   if (!line.empty()) {
			   stringstream ss(line);
			   int fromState, toState;
			   string symStr;

			   getline(ss, symStr, '\t');
			   fromState = stoi(symStr);
			   getline(ss, symStr, '\t');
			   Symbol sym = Symbol::deserialize(symStr);
			   ss >> toState;

			   if (section == "TERMINAL") {
				   transitions[{fromState, sym}] = toState;
			   }
			   else if (section == "NON_TERMINAL") {
				   nonTerminalTransitions[{fromState, sym}] = toState;
			   }
		   }
	   }
   }
